/*
 //  TextDownloader.m
 //  TextDownloader
 //
 //  Created by Brennan Stehling on 10/25/09.
 //  Copyright 2009 mwiphonesdk. All rights reserved.
 */

#import "TextDownloader.h"

@implementation TextDownloader

#pragma mark - Properties

@synthesize connection				= _connection;
@synthesize contentType				= _contentType;
@synthesize text					= _text;
@synthesize supportedContentTypes	= _supportedContentTypes;
@synthesize delegate				= _delegate;

#pragma mark - Memory Management

- (void) dealloc {
	[self.connection release];
	[self.contentType release];
	[self.text release];
	[self.supportedContentTypes release];
	[self.delegate release];
	[super dealloc];
}

#pragma mark - Public

- (void)downloadText:(NSString *)urlString delegate:(id)delegate {
	NSLog(@"downloadText: %@", urlString);
	self.delegate = delegate;
	[self _startReceive:urlString];
}

- (BOOL)isSupportedContentType {
	if (_contentType == nil) {
		return FALSE;
	}
	
	BOOL match = false;
	
	int i;
	for (i=0; i<_supportedContentTypes.count; i++) {
		NSRange range = [_contentType rangeOfString:[_supportedContentTypes objectAtIndex:i]];
		if (range.location != NSNotFound) {
			match = TRUE;
			break;
		}
	}
	
	return match;
}

- (BOOL)isReceiving {
    return (self.connection != nil);
}

#pragma mark - Private

- (void)_startReceive:(NSString *)urlString {	
	NSURL *url = [[NSURL alloc] initWithString:urlString];
	NSURLRequest *request;
    
    assert(self.connection == nil);
	
	// Open a connection for the URL.
	request = [NSURLRequest requestWithURL:url];
	assert(request != nil);
	
	// turn on network activity indicator
	[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
	
	self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
	assert(self.connection != nil);
	
	[url release];
}

- (void)_stopReceiveWithStatus:(NSString *)errorMessage
// Shuts down the connection and displays the result (statusString == nil) 
// or the error status (otherwise).
{
	// turn off network activity indicator
	[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
	
    if (self.connection != nil) {
        [self.connection cancel];
        self.connection = nil;
    }
	
	if (errorMessage != nil) {
		// report that the download failed
		if([[self delegate] respondsToSelector:@selector(downloadTextFailed:)]) {
			[[self delegate] downloadTextFailed:errorMessage];
		}
	}
}

#pragma mark - Networking

- (void)connection:(NSURLConnection *)theConnection didReceiveResponse:(NSURLResponse *)response
// A delegate method called by the NSURLConnection when the request/response 
// exchange is complete.
{
#pragma unused(theConnection)
    NSHTTPURLResponse	* httpResponse;
	
    assert(theConnection == self.connection);
	
	if (self.supportedContentTypes == nil) {
		self.supportedContentTypes = [NSArray arrayWithObjects: @"text/plain", @"text/html", nil];
	}
    
    httpResponse = (NSHTTPURLResponse *) response;
    assert( [httpResponse isKindOfClass:[NSHTTPURLResponse class]] );
    
	if ((httpResponse.statusCode / 100) != 2) {
        [self _stopReceiveWithStatus:[NSString stringWithFormat:@"HTTP error %zd", (ssize_t) httpResponse.statusCode]];
    } else {
        self.contentType = [httpResponse.allHeaderFields objectForKey:@"Content-Type"];
        if (_contentType == nil) {
            [self _stopReceiveWithStatus:@"No Content-Type!"];
        } else {
			if (![self isSupportedContentType]) {
				[self _stopReceiveWithStatus:[NSString stringWithFormat:@"Unsupported Content-Type (%@)", _contentType]];
			}
        }
	}
}

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
// A delegate method called by the NSURLConnection as data arrives.  We just 
// append the data to an NSMutableString.
{
#pragma unused(theConnection)
    assert(theConnection == self.connection);
	
	// allocate the instance variable (retain until dealloc)
	if (_text == nil){
		_text = [[NSMutableString alloc] init];
	}
	
	NSString* string = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
	[self.text appendString:string];
	[string release];
}

- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error
// A delegate method called by the NSURLConnection if the connection fails. 
// We shut down the connection and display the failure.
{
#pragma unused(theConnection)
#pragma unused(error)
    assert(theConnection == self.connection);
    
    [self _stopReceiveWithStatus:@"Connection failed"];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
// A delegate method called by the NSURLConnection when the connection has been 
// done successfully.
{
#pragma unused(theConnection)
    assert(theConnection == self.connection);
    
    [self _stopReceiveWithStatus:nil];
	// call the downloadTextFinished delegate (callback)
	if([[self delegate] respondsToSelector:@selector(downloadTextFinished:)]) {
		[[self delegate] downloadTextFinished:self.text];
	}
}

@end
